package com.szamc.tableroundapi.service;

import com.szamc.tableroundapi.model.BaseTable.BaseTableFormatData;
import com.szamc.tableroundapi.model.BaseTable.BaseTableOption;
import lombok.var;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.stream.Collectors;

public class BaseTableRoundApiService<T> {

    private static List<BaseTableOption> baseTableOptions;
    private static double divideNumber;
    private static int precision;
    public List<LinkedHashMap> GetRoundTable(List<LinkedHashMap> tableList, List<BaseTableOption> _baseTableOptions,double _divideNumber,int _precision) throws NoSuchFieldException, IllegalAccessException {
        BaseTableRoundApiService.baseTableOptions = _baseTableOptions;
        BaseTableRoundApiService.divideNumber = _divideNumber;
        BaseTableRoundApiService.precision = _precision;

        var forMatDataList = GetForMatDataList(tableList);
        var sum = GetSum(forMatDataList);
        var floorSum = GetFloorSum(forMatDataList);
        var addCount = (int) Math.round(sum) - floorSum;
        forMatDataList.sort(Comparator.comparing(BaseTableFormatData::getDecimalPart).reversed());//排序
        var addIds = forMatDataList.subList(0, addCount)
                .stream()
                .map(BaseTableFormatData::getId)
                .collect(Collectors.toList());
        return GetRoundList(tableList, baseTableOptions, addIds);
    };

    //按字段展开
    private ArrayList<BaseTableFormatData> GetForMatDataList(List<LinkedHashMap> tableList) throws NoSuchFieldException, IllegalAccessException {
        var tableRows = new ArrayList<BaseTableFormatData>();
        for (int i = 0; i < tableList.size(); i++) {
            for (BaseTableOption baseTableOption : baseTableOptions) {
                if (baseTableOption.getFieldType() != 0) {
                    LinkedHashMap obj = tableList.get(i);
                    var fieldType = baseTableOption.getFieldType();
                    var _value = GetProcessValue(((double) obj.get(baseTableOption.getFieldName())));
                    var _formatData = new BaseTableFormatData(
                            fieldType == 1 ? _value : -_value,
                            baseTableOption.getFieldName(),
                            baseTableOption.getFieldType(),
                            i);
                    tableRows.add(_formatData);
                }
            }
        }
        return tableRows;
    }

    private double GetProcessValue(double OriginalValue){
        return  (OriginalValue/divideNumber)*Math.pow(10, precision);
    }

    private double GetOriginalValue(double ProcessValue,int fieldType){
        double result = round(ProcessValue/Math.pow(10, precision), precision);
        return fieldType==1?result:-result;
    }
    private static double round(double value, int places) {
        BigDecimal bd = BigDecimal.valueOf(value);
        bd = bd.setScale(places, RoundingMode.DOWN);
        return bd.doubleValue();
    }

    private String GetTableId(int rowIndex, String fieldName) {
        return rowIndex + "_" + fieldName;
    }

    //获取所有数字的总和
    private double GetSum(List<BaseTableFormatData> forMatDataList) {
        double sum = 0;
        for (BaseTableFormatData item : forMatDataList) {
            sum += item.getValue();
        }
        return sum;
    }

    //获取所有整数部分的和
    private int GetFloorSum(List<BaseTableFormatData> forMatDataList) {
        int sum = 0;
        for (BaseTableFormatData item : forMatDataList) {
            sum += item.getIntegerPart();
        }
        return sum;
    }

    //给原来的List按条件+1
    private List<LinkedHashMap> GetRoundList(List<LinkedHashMap> tableList, List<BaseTableOption> baseTableOptions, List<String> Ids) throws NoSuchFieldException, IllegalAccessException {
        for (int i = 0; i < tableList.size(); i++) {
            for (BaseTableOption item : baseTableOptions) {
                var _id = GetTableId(i, item.getFieldName());
                LinkedHashMap obj = tableList.get(i);
                int fieldType = item.getFieldType();
                var _oldValue = (double) obj.get(item.getFieldName());
                var _newValue = Math.floor(fieldType== 1 ? GetProcessValue(_oldValue):-GetProcessValue(_oldValue));
                var addNumber = 1;
                if (Ids.contains(_id)) {
                    obj.replace(item.getFieldName(), GetOriginalValue(_newValue + addNumber,fieldType));
                } else {
                    obj.replace(item.getFieldName(), GetOriginalValue(_newValue,fieldType));
                }
            }
        }
        return tableList;
    }
}